package com.yzk.train.business.service;

import cn.hutool.core.date.DateTime;
import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.alibaba.fastjson.JSON;
import com.yzk.train.business.entity.ConfirmOrder;
import com.yzk.train.business.enums.ConfirmOrderStatusEnum;
import com.yzk.train.business.mapper.ConfirmOrderMapper;
import com.yzk.train.business.request.ConfirmOrderDoReq;
import com.yzk.train.business.request.ConfirmOrderTicketReq;
import com.yzk.train.common.constant.MQConstant;
import com.yzk.train.common.context.MemberLoginContext;
import com.yzk.train.common.exception.BusinessException;
import com.yzk.train.common.exception.ExceptionEnum;
import com.yzk.train.common.utils.SnowUtil;
import jakarta.annotation.Resource;
import org.apache.rocketmq.spring.core.RocketMQTemplate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.slf4j.MDC;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

@Service
public class BeforeConfirmOrderService {

    private static final Logger LOG = LoggerFactory.getLogger(BeforeConfirmOrderService.class);

    @Resource
    private ConfirmOrderMapper confirmOrderMapper;

    @Resource
    public RocketMQTemplate rocketMQTemplate;

    @SentinelResource(value = "beforeDoConfirm", blockHandler = "beforeDoConfirmBlock")
    public Long beforeDoConfirm(ConfirmOrderDoReq req) {
        Date date = req.getDate();
        String trainCode = req.getTrainCode();
        String start = req.getStart();
        String end = req.getEnd();
        List<ConfirmOrderTicketReq> tickets = req.getTickets();
        // 保存确认订单表，状态初始
        DateTime now = DateTime.now();
        ConfirmOrder confirmOrder = new ConfirmOrder();
        confirmOrder.setId(SnowUtil.getSnowflakeNextId());
        confirmOrder.setCreateTime(now);
        confirmOrder.setUpdateTime(now);
        confirmOrder.setMemberId(MemberLoginContext.getId());
        confirmOrder.setDate(date);
        confirmOrder.setTrainCode(trainCode);
        confirmOrder.setStart(start);
        confirmOrder.setEnd(end);
        confirmOrder.setDailyTrainTicketId(req.getDailyTrainTicketId());
        confirmOrder.setStatus(ConfirmOrderStatusEnum.INIT.getCode());
        confirmOrder.setTickets(JSON.toJSONString(tickets));
        confirmOrderMapper.insert(confirmOrder);
        // 发送MQ消息，异步选座
        req.setLogId(MDC.get("LOG_ID"));
        String reqJson = JSON.toJSONString(req);
        rocketMQTemplate.convertAndSend(MQConstant.CONFIRM_ORDER, reqJson);
        LOG.info("发送【确认订单】MQ消息：{}", reqJson);
        return confirmOrder.getId();
    }

    /**
     * 降级方法，需包含限流方法的所有参数和BlockException参数
     *
     * @param req
     * @param e
     */
    public void beforeDoConfirmBlock(ConfirmOrderDoReq req, BlockException e) {
        LOG.info("购票请求被限流：{}", req);
        throw new BusinessException(ExceptionEnum.CONFIRM_ORDER_FLOW_EXCEPTION);
    }

}
